<script setup lang="ts">
import { onMounted, onUnmounted, ref, watch } from "vue"
const path = window.require("node:path")
const fs = window.require("fs")
import { ElMessage } from "element-plus"
import { UnderwayTrain } from "../../../api/train"
import VueOfficePdf from "@vue-office/pdf"
import VueOfficeExcel from "@vue-office/excel"
import VueOfficeDocx from "@vue-office/docx"
import "@vue-office/excel/lib/index.css"
import axios from "axios"
import { ElLoading } from "element-plus"
import router from "../../../router"
const excelOption = {
  xls: false, //预览xlsx文件设为false；预览xls文件设为true
  minColLength: 0, // excel最少渲染多少列，如果想实现xlsx文件内容有几列，就渲染几列，可以将此值设置为0.
  minRowLength: 0, // excel最少渲染多少行，如果想实现根据xlsx实际函数渲染，可以将此值设置为0.
  widthOffset: 10, //如果渲染出来的结果感觉单元格宽度不够，可以在默认渲染的列表宽度上再加 Npx宽
  heightOffset: 10, //在默认渲染的列表高度上再加 Npx高
  beforeTransformData: (workbookData) => {
    return workbookData
  }, //底层通过exceljs获取excel文件内容，通过该钩子函数，可以对获取的excel文件内容进行修改，比如某个单元格的数据显示不正确，可以在此自行修改每个单元格的value值。
  transformData: (workbookData) => {
    return workbookData
  } //将获取到的excel数据进行处理之后且渲染到页面之前，可通过transformData对即将渲染的数据及样式进行修改，此时每个单元格的text值就是即将渲染到页面上的内容
}
const video = ref("")

const formattedTime = ref("00:00:00")
const options = {
  audioBitsPerSecond: 128000,
  videoBitsPerSecond: 1e6,
  mimeType: "video/webm;codecs=vp9"
}
let uploadTipText = "正在上传，请耐心等待，大概需要五分钟,成功后将自动返回首页！"
let recorder
let blobs = []
let interval
const totalSeconds = ref(0)
// 屏幕录制
const screenRecord = async function () {
  await navigator.webkitGetUserMedia(
    {
      cursor: "never",
      audio: {
        mandatory: {
          chromeMediaSource: "desktop"
        }
      },
      video: {
        mandatory: {
          frameRate: { ideal: 30 },
          chromeMediaSource: "desktop",
          chromeMediaSourceId: "screen:0:0",
          maxWidth: window.screen.width,
          maxHeight: window.screen.height
        }
      }
    },
    handleStream,
    (err) => {
      console.error(err)
    }
  )
}

function handleStream(screenStream) {
  const screenVideoTrack = screenStream.getVideoTracks()[0]
  const screenAudioTrack = screenStream.getAudioTracks()[0]
  const mediaStream = new MediaStream([screenVideoTrack])
  mediaStream.addTrack(screenAudioTrack)
  recorder = new MediaRecorder(mediaStream, options)
  blobs = []
  recorder.ondataavailable = function(event) {
    blobs.push(event.data)
  }
  recorder.start()
}

function toArrayBuffer(blob, cb) {
  const fileReader = new FileReader()
  fileReader.onload = function() {
    const arrayBuffer = fileReader.result
    cb(arrayBuffer)
  }
  fileReader.readAsArrayBuffer(blob)
}

function toBuffer(ab) {
  const buffer = new Buffer(ab.byteLength)
  const arr = new Uint8Array(ab)
  for (let i = 0; i < arr.byteLength; i++) {
    buffer[i] = arr[i]
  }
  return buffer
}

function stopRecord() {
  recorder.onstop = () => {
    toArrayBuffer(new Blob(blobs, { type: "video/webm" }), (chunk) => {
      const buffer = toBuffer(chunk)
      const NameString = "screen-" + info.value.name
      const webmName = NameString + ".webm"
      const mp4Name = NameString + ".mp4"
      const webmPath = path.join(".\\video\\", webmName)
      const mp4Path = path.join(".\\video\\", mp4Name)
      fs.writeFile(webmPath, buffer, async function(err) {
        if (!err) {
          const res = await window.electron.ipcRenderer.sendSync("exec", webmPath, mp4Path)
          console.log(res, "exec")
          uploadTipText = `请耐心等待，大概需要${Math.ceil(totalSeconds.value / 600)}分钟,成功后自动返回首页！`
          const Path = path.join(window.electron.ipcRenderer.sendSync("path"), "../..", mp4Path)
          fs.readFile(Path, (err, data) => {
            if (err) {
              console.log("读取文件出错，可能文件不完整")
            } else {
              const file = new File([data], Path, { type: "video/mp4" })
              const formData = new FormData()
              formData.append("formFile", file)
              axios
                .post(
                  "http://192.168.2.25:5173/api/UploadFile/UploadVideoFiles?type=screen",
                  formData,
                  {
                    headers: {
                      "Content-Type": "multipart/form-data"
                    }
                  }
                )
                .then((res) => {
                  if (res.data.data.result.screenVideo && res.data.data.result.cameraVideo) {
                    loading.close()
                    router.push("/")
                  }
                  if (!cameraId) {
                    loading.close()
                    router.push("/")
                  }
                })
            }
          })
        }
      })
    })
  }
  recorder.stop()
}

function startCounting() {
  const startTime = Date.now()
  totalSeconds.value = 0

  interval = setInterval(() => {
    totalSeconds.value = Math.floor((Date.now() - startTime) / 1000)
  }, 1000)

  onUnmounted(() => {
    clearInterval(interval)
  })

  watch(totalSeconds, (newValue) => {
    const hours = Math.floor(newValue / 3600)
    const minutes = Math.floor((newValue % 3600) / 60)
    const seconds = newValue % 60
    formattedTime.value = `${pad(hours)}:${pad(minutes)}:${pad(seconds)}`
  })
}

function pad(num) {
  return num.toString().padStart(2, "0")
}

let cameraId = ""
let cameraRecorder
let cameraBlob = []

function videoRecord() {
  navigator.mediaDevices
    .enumerateDevices()
    .then((devices) => devices.filter((d) => d.kind === "videoinput"))
    .then((devices) => {
      if (devices.length == 0) {
        ElMessage.error("No devices found")
      } else {
        cameraId = devices[0].deviceId
        const stream = navigator.mediaDevices
          .enumerateDevices()
          .then((device) => device.find((d) => d.kind === "videoinput" && d.deviceId === cameraId))
          .then((video) =>
            navigator.mediaDevices.getUserMedia({
              video: {
                video,
                width: 1280,
                height: 720,
                frameRate: 30
              }
            })
          )
        stream
          .then(async (Mediastream) => {
            video.value.srcObject = Mediastream
            video.value.play()
            video.value.muted = true
            const audioTracks = await navigator.mediaDevices
              .getUserMedia({ audio: true, video: false })
              .then((mediaStream) => mediaStream.getAudioTracks()[0])
            Mediastream.addTrack(audioTracks)
            cameraRecorder = new MediaRecorder(Mediastream, options)
            cameraBlob = []
            cameraRecorder.ondataavailable = function(event) {
              cameraBlob.push(event.data)
            }
            cameraRecorder.start()
          })
          .catch((err) => console.error("startRecord error", err))
      }
    }) // devices 为摄像头数组);
}

function stopVideoRecord() {
  cameraRecorder.onstop = () => {
    toArrayBuffer(new Blob(cameraBlob, { type: "video/webm" }), (chunk) => {
      const buffer = toBuffer(chunk)
      const NameString = "camera-" + info.value.name
      const webmName = NameString + ".webm"
      const mp4Name = NameString + ".mp4"
      const webmPath = path.join(".\\video\\", webmName)
      const mp4Path = path.join(".\\video\\", mp4Name)
      console.log(webmPath, mp4Path)
      fs.writeFile(webmPath, buffer, async function(err) {
        if (!err) {
          const res = await window.electron.ipcRenderer.sendSync("exec1", webmPath, mp4Path)
          console.log(res, "exec")
          uploadTipText = `请耐心等待，大概需要${Math.ceil(totalSeconds.value / 600)}分钟,成功后自动返回首页！`
          const Path = path.join(window.electron.ipcRenderer.sendSync("path"), "../..", mp4Path)
          fs.readFile(Path, (err, data) => {
            if (err) {
              console.log("读取文件出错，可能文件不完整")
            } else {
              const file = new File([data], Path, { type: "video/mp4" })
              const formData = new FormData()
              formData.append("formFile", file)
              axios
                .post(
                  "http://192.168.2.25:5173/api/UploadFile/UploadVideoFiles?type=camera",
                  formData,
                  {
                    headers: {
                      "Content-Type": "multipart/form-data"
                    }
                  }
                )
                .then((res) => {
                  if (res.data.data.result.screenVideo && res.data.data.result.cameraVideo) {
                    loading.close()
                    router.push("/")
                  }
                  if (!cameraId) {
                    loading.close()
                    router.push("/")
                  }
                })
            }
          })
        }
      })
    })
  }
  cameraRecorder.stop()
}

function start() {
  screenRecord()
  videoRecord()
  startCounting()
}

let loading

function stop() {
  clearInterval(interval)
  if (cameraId) {
    stopVideoRecord()
  }
  stopRecord()
  loading = ElLoading.service({
    lock: true,
    text: uploadTipText,
    background: "rgba(0, 0, 0, 0.7)"
  })
}

onMounted(() => {
  getInfo()
  start()
})

const info = ref({})
const check = ref({
  url: "",
  type: ""
})

const selected = function(file) {
  check.value.url = "http://192.168.2.25:5173/file/" + file.url
  if (file.type.indexOf("image") != -1) {
    check.value.type = "image"
  } else if (file.type.indexOf("video") != -1) {
    check.value.type = "video"
  } else if (file.type.indexOf("pdf") != -1) {
    check.value.type = "pdf"
  } else if (file.type.indexOf("word") != -1) {
    check.value.type = "word"
  } else if (file.type.indexOf("sheet") != -1) {
    check.value.type = "excel"
  }
}

function getInfo() {
  UnderwayTrain().then((res) => {
    if (res.ret) {
      info.value = res.data
      if (info.value.files) {
        info.value.files = JSON.parse(info.value.files)
      }
    }
  })
}

function renderedHandler() {
  console.log("渲染完成")
}

function errorHandler() {
  ElMessage.error("渲染失败,请检查文件完好性")
}

// function afterFileSelected(event) {
//   const file = event.target.files[0]
//   console.log(file)
// }
</script>
<template>
  <div class="h-full w-full p-0 m-0">
    <el-container class="h-full">
      <el-header height="5%" class="bg-blue-300">
        <div class="w-full h-full flex justify-between items-center">
          <el-button type="primary" @click="stop">结束会议</el-button>
          {{ info.name }}
          <div class="text-red-500">正在录制🔴{{ formattedTime }}</div>
        </div>
      </el-header>
      <el-container>
        <el-aside width="300px">
          <div v-for="value in info.files" :key="value.name">
            <el-card @click="selected(value)">{{ value.name }}</el-card>
          </div>
        </el-aside>
        <el-main class="w-full h-full">
          <div class="w-full h-full flex justify-center items-center">
            <video v-if="check.type == 'video'" autoplay controls :src="check.url"></video>
            <el-image v-else-if="check.type == 'image'" :src="check.url" />
            <vue-office-pdf
              v-else-if="check.type == 'pdf'"
              :src="check.url"
              style="height: 90vh; width: 90vw"
              @rendered="renderedHandler"
              @error="errorHandler"
            />
            <vue-office-docx
              v-else-if="check.type == 'word'"
              :src="check.url"
              style="height: 90vh; width: 90vw"
              @rendered="renderedHandler"
              @error="errorHandler"
            />
            <vue-office-excel
              v-else-if="check.type == 'excel'"
              :src="check.url"
              :options="excelOption"
              style="height: 90vh; width: 90vw"
              @rendered="renderedHandler"
              @error="errorHandler"
            />
            <video v-else ref="video" style="height: 90vh; width: 90vw"></video>
          </div>
        </el-main>
      </el-container>
    </el-container>
  </div>
</template>

<style scoped></style>
